#include <Engine/StdAfx.h>
#include <Engine/SceneGraph/Scene.h>
#include <Engine/IObject.h>
#include <Engine/SceneGraph/SpatialObject.h>
#include <Engine/GlobalEnv.h>
#include <Engine/IEngine.h>
#include <Engine/IRenderer.h>
#include <Engine/ICamera.h>

using namespace fastbird;

//----------------------------------------------------------------------------
Scene::Scene()
{
	mVisibleObjects.reserve(1000);
}

//----------------------------------------------------------------------------
Scene::~Scene()
{

}

//----------------------------------------------------------------------------
bool Scene::AttachObject(SpatialObject* pSpatialObject)
{
    auto it = std::find(mSpatialObjects.begin(), mSpatialObjects.end(), pSpatialObject);
    if (it!=mSpatialObjects.end())
    {
        return false;
    }

    mSpatialObjects.push_back(pSpatialObject);
    pSpatialObject->OnAttachedToScene(this);

    return true;
}

//----------------------------------------------------------------------------
bool Scene::DetachObject(SpatialObject* pSpatialObject)
{
    auto it = std::find(mSpatialObjects.begin(), mSpatialObjects.end(), pSpatialObject);
    if (it != mSpatialObjects.end())
    {
        pSpatialObject->OnDetachedFromScene(this);
        mSpatialObjects.erase(it);
        return true;
    }
    
    return false;
}

//----------------------------------------------------------------------------
bool Scene::AttachObject(IObject* pObject)
{
    auto it = std::find(mObjects.begin(), mObjects.end(), pObject);
    if (it!= mObjects.end())
    {
        return false;
    }

    mObjects.push_back(pObject);
    pObject->OnAttachedToScene(this);

    return true;
}

//----------------------------------------------------------------------------
bool Scene::DetachObject(IObject* pObject)
{
    auto it = std::find(mObjects.begin(), mObjects.end(), pObject);
    if (it!= mObjects.end())
    {
        pObject->OnDetachedFromScene(this);
        mObjects.erase(it);
        return true;
    }

    return false;
}

//----------------------------------------------------------------------------
void Scene::MakeVisibleSet()
{
	mVisibleObjects.clear();
	auto it = mSpatialObjects.begin(), itEnd = mSpatialObjects.end();
	for (; it!=itEnd; it++)
	{
		if ( gEnv->pEngine->GetRenderer()->GetCamera()->IsCulled((*it)->GetBoundingVolume()) )
			continue;
		mVisibleObjects.push_back(*it);
	}
}

//----------------------------------------------------------------------------
void Scene::PreRender()
{
	MakeVisibleSet();
	auto it = mVisibleObjects.begin(), itEnd = mVisibleObjects.end();
	for (; it!=itEnd; it++)
	{
		(*it)->PreRender();
	}
}

//----------------------------------------------------------------------------
void Scene::Render()
{
	auto it = mVisibleObjects.begin(), itEnd = mVisibleObjects.end();
	for (; it!=itEnd; it++)
	{
		(*it)->Render();
	}
}